package com.elong.android.specialhouse.ui;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.HeaderViewListAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.elong.android.specialhouse.R;

import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.Date;

public class SuperListView extends ListView implements OnScrollListener {

    private final static int RELEASE_To_REFRESH = 0;
    private final static int PULL_To_REFRESH = 1;
    private final static int REFRESHING = 2;
    private final static int DONE = 3;
    private final static int LOADING = 4;

    private final static int RATIO = 3;

    private LayoutInflater mInflater;
    private LinearLayout mHeadView;
    private TextView mTipsTextview;
    private TextView mLastUpdatedTextView;
    private ImageView mArrowImageView;
    private ProgressBar mProgressBar;

    private RotateAnimation mAnimation;
    private RotateAnimation mReverseAnimation;
    private boolean mIsRecored;
    private int mHeadContentHeight;
    private int mStartY;
    private int mFirstItemIndex;
    private int mCurrentState;
    private boolean mIsBack;
    private OnPullDownRefreshListener mRefreshListener;
    private boolean mIsRefreshable;

    public RelativeLayout mFooterRelative;
    public TextView mFooterTextView;
    public ProgressBar mFooterProgressBar;
    public int mLastItem;
    private boolean mIsOnLoading;
    private boolean isLastPage = false;

    private OnLoadMoreListener onLoadMoreListener;
    private Context mContext;
    public boolean mBusy = false;

    // 没有更多提示
    private boolean isBottomTip = false;
    private String bottomTipString = "";

    // 上/下拉的超时处理
    private final int TIMEOUT_TIME = 15000;// 超时时间(应与联网模块保持一致)
    private boolean isRefreshSuccess = false;
    private boolean isLoadmoreSuccess = false;
    private static final int TIMEOUT_REFRESH = 0;// 下拉刷新超时
    private static final int TIMEOUT_LOADMORE = 1;// 载入更多超时

    private Handler mHandler = new UIHandler(this);

    public SuperListView(Context context) {
        super(context);
        mContext = context;
        init(context);
    }

    public SuperListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        /*
		 * mGestureDetector = new GestureDetector(new YScrollDetector());
		 * setFadingEdgeLength(0);
		 */
        init(context);
    }

	/*
	 * @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return
	 * super.onInterceptTouchEvent(ev) && mGestureDetector.onTouchEvent(ev); }
	 * 
	 * class YScrollDetector extends SimpleOnGestureListener {
	 * 
	 * @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float
	 * distanceX, float distanceY) { if (distanceY != 0 && distanceX != 0) {
	 * 
	 * } if (Math.abs(distanceY) >= Math.abs(distanceX)) { return true; } return
	 * false; } }
	 */

    /**
     * 设置listView头部下拉刷新的样式
     *
     * @param color         文字的颜色
     * @param arrowResource 箭头的Resource ID
     * @param loadingStyle  ProgressBar的loading样式 by Ang.Chen
     */

    public void setHeadStyle(int color, int arrowResource, Drawable loadingStyle) {
        mTipsTextview.setTextColor(color);
        mLastUpdatedTextView.setTextColor(color);
        mArrowImageView.setImageResource(arrowResource);
        mProgressBar.setIndeterminateDrawable(loadingStyle);
    }

    private void init(Context context) {
        setCacheColorHint(context.getResources().getColor(android.R.color.transparent));
        mInflater = LayoutInflater.from(context);
        mHeadView = (LinearLayout) mInflater.inflate(R.layout.listview_header, null);
        mArrowImageView = (ImageView) mHeadView.findViewById(R.id.head_arrowImageView);
        mArrowImageView.setMinimumWidth(70);
        mArrowImageView.setMinimumHeight(50);
        mProgressBar = (ProgressBar) mHeadView.findViewById(R.id.head_progressBar);
        mTipsTextview = (TextView) mHeadView.findViewById(R.id.head_tipsTextView);
        mLastUpdatedTextView = (TextView) mHeadView.findViewById(R.id.head_lastUpdatedTextView);
        measureView(mHeadView);
        mHeadContentHeight = mHeadView.getMeasuredHeight();
        mHeadView.setPadding(0, -1 * mHeadContentHeight, 0, 0);
        mHeadView.invalidate();
        addHeaderView(mHeadView, null, false);
        setOnScrollListener(this);
        mAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        mAnimation.setInterpolator(new LinearInterpolator());
        mAnimation.setDuration(250);
        mAnimation.setFillAfter(true);

        mReverseAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        mReverseAnimation.setInterpolator(new LinearInterpolator());
        mReverseAnimation.setDuration(200);
        mReverseAnimation.setFillAfter(true);

        mCurrentState = DONE;
        mIsRefreshable = false;
        mIsOnLoading = false;
        mFooterRelative = (RelativeLayout) mInflater.inflate(R.layout.listview_footer, null);
        mFooterTextView = (TextView) mFooterRelative.findViewById(R.id.footer_loadmore_text);
        mFooterProgressBar = (ProgressBar) mFooterRelative.findViewById(R.id.footer_progressbar);
    }

    public void showRefreshDemo() {
        mCurrentState = REFRESHING;
        changeHeaderViewByState();
        onRefresh();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mIsRefreshable) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    if (mFirstItemIndex == 0 && !mIsRecored) {
                        mIsRecored = true;
                        mStartY = (int) event.getY();
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (mCurrentState != REFRESHING && mCurrentState != LOADING) {
                        if (mCurrentState == DONE) {
                        }
                        if (mCurrentState == PULL_To_REFRESH) {
                            mCurrentState = DONE;
                            changeHeaderViewByState();
                        }
                        if (mCurrentState == RELEASE_To_REFRESH) {
                            mCurrentState = REFRESHING;
                            changeHeaderViewByState();
                            onRefresh();
                        }
                    }
                    mIsRecored = false;
                    mIsBack = false;
                    break;
                case MotionEvent.ACTION_MOVE:
                    int tempY = (int) event.getY();
                    if (!mIsRecored && mFirstItemIndex == 0) {
                        mIsRecored = true;
                        mStartY = tempY;
                    }
                    if (mCurrentState != REFRESHING && mIsRecored && mCurrentState != LOADING) {
                        if (mCurrentState == RELEASE_To_REFRESH) {
                            setSelection(0);
                            if (((tempY - mStartY) / RATIO < mHeadContentHeight) && (tempY - mStartY) > 0) {
                                mCurrentState = PULL_To_REFRESH;
                                changeHeaderViewByState();
                            } else if (tempY - mStartY <= 0) {
                                mCurrentState = DONE;
                                changeHeaderViewByState();
                            }
                        }
                        if (mCurrentState == PULL_To_REFRESH) {
                            setSelection(0);
                            if ((tempY - mStartY) / RATIO >= mHeadContentHeight) {
                                mCurrentState = RELEASE_To_REFRESH;
                                mIsBack = true;
                                changeHeaderViewByState();
                            } else if (tempY - mStartY <= 0) {
                                mCurrentState = DONE;
                                changeHeaderViewByState();
                            }
                        }
                        if (mCurrentState == DONE) {
                            if (tempY - mStartY > 0) {
                                mCurrentState = PULL_To_REFRESH;
                                changeHeaderViewByState();
                            }
                        }
                        if (mCurrentState == PULL_To_REFRESH) {
                            mHeadView.setPadding(0, -1 * mHeadContentHeight + (tempY - mStartY) / RATIO, 0, 0);
                        }
                        if (mCurrentState == RELEASE_To_REFRESH) {
                            mHeadView.setPadding(0, (tempY - mStartY) / RATIO - mHeadContentHeight, 0, 0);
                        }
                    }
                    break;
            }
        }
        return super.onTouchEvent(event);
    }

    private void changeHeaderViewByState() {
        switch (mCurrentState) {
            case RELEASE_To_REFRESH:
                mArrowImageView.setVisibility(View.VISIBLE);
                mProgressBar.setVisibility(View.GONE);
                mTipsTextview.setVisibility(View.VISIBLE);
                mLastUpdatedTextView.setVisibility(View.VISIBLE);
                mArrowImageView.clearAnimation();
                mArrowImageView.startAnimation(mAnimation);
                mTipsTextview.setText(R.string.remind_pull);
                break;
            case PULL_To_REFRESH:
                mProgressBar.setVisibility(View.GONE);
                mTipsTextview.setVisibility(View.VISIBLE);
                mLastUpdatedTextView.setVisibility(View.VISIBLE);
                mArrowImageView.clearAnimation();
                mArrowImageView.setVisibility(View.VISIBLE);
                if (mIsBack) {
                    mIsBack = false;
                    mArrowImageView.clearAnimation();
                    mArrowImageView.startAnimation(mReverseAnimation);
                    mTipsTextview.setText(R.string.pull_down);
                } else {
                    mTipsTextview.setText(R.string.pull_down);
                }
                break;
            case REFRESHING:
                mHeadView.setPadding(0, 0, 0, 0);
                mProgressBar.setVisibility(View.VISIBLE);
                mArrowImageView.clearAnimation();
                mArrowImageView.setVisibility(View.GONE);
                mTipsTextview.setText(R.string.reflasing);
                mLastUpdatedTextView.setVisibility(View.VISIBLE);
                break;
            case DONE:
                mHeadView.setPadding(0, -1 * mHeadContentHeight, 0, 0);
                mProgressBar.setVisibility(View.GONE);
                mArrowImageView.clearAnimation();
                // mArrowImageView.setImageResource(R.drawable.pull_arrow_down);
                mTipsTextview.setText(R.string.reflash_done);
                mLastUpdatedTextView.setVisibility(View.VISIBLE);
                break;
        }
    }

    public void setOnRefreshListener(OnPullDownRefreshListener refreshListener) {
        this.mRefreshListener = refreshListener;
        mIsRefreshable = refreshListener != null;
    }

    public interface OnPullDownRefreshListener {
        public void onRefresh();
    }

    public void onRefreshComplete() {
        mHandler.removeMessages(TIMEOUT_REFRESH);
        mIsOnLoading = false;
        isRefreshSuccess = true;
        mCurrentState = DONE;
        mLastUpdatedTextView.setText(mContext.getString(R.string.last_update_time) + getCurrentDateTime());
        changeHeaderViewByState();
    }

    private void onRefresh() {
        if (mRefreshListener != null && !mIsOnLoading) {
            mIsOnLoading = true;
            mRefreshListener.onRefresh();
            isRefreshSuccess = false;
            Message msg = Message.obtain();
            msg.what = TIMEOUT_REFRESH;
            mHandler.sendMessageDelayed(msg, TIMEOUT_TIME);
        }
    }

    public interface OnLoadMoreListener {
        public void onLoadMore();
    }

    public void setOnLoadMoreListener(OnLoadMoreListener loadMore) {
        this.onLoadMoreListener = loadMore;
    }

    private void onLoadMore() {
        if (getFooterViewsCount() == 0) {
            addFooterView(mFooterRelative);
        }

        if (onLoadMoreListener != null && !mIsOnLoading) {
            mIsOnLoading = true;
            onLoadMoreListener.onLoadMore();
            isLoadmoreSuccess = false;
            Message msg = Message.obtain();
            msg.what = TIMEOUT_LOADMORE;
            mHandler.sendMessageDelayed(msg, TIMEOUT_TIME);
        }
    }

    public void onLoadMoreComplete() {
        mHandler.removeMessages(TIMEOUT_LOADMORE);
        isLoadmoreSuccess = true;
        mIsOnLoading = false;
        if (getFooterViewsCount() > 0) {
            removeFooterView(mFooterRelative);
        }
    }

    private void measureView(View child) {
        ViewGroup.LayoutParams p = child.getLayoutParams();
        if (p == null) {
            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
        int lpHeight = p.height;
        int childHeightSpec;
        if (lpHeight > 0) {
            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
        } else {
            childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }

        child.measure(childWidthSpec, childHeightSpec);
    }

    public void setAdapter(BaseAdapter adapter) {
        mLastUpdatedTextView.setText(mContext.getString(R.string.last_update_time) + getCurrentDateTime());
        super.setAdapter(adapter);
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        mFirstItemIndex = firstVisibleItem;
        mLastItem = firstVisibleItem + visibleItemCount;
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (this.getAdapter() == null) {
            return;
        }
        if (this.getAdapter().getCount() == 0) {
            return;
        }
        if (mIsOnLoading) {
            return;
        }
        if (mLastItem == this.getAdapter().getCount() && scrollState == SCROLL_STATE_IDLE && !isLastPage) {
            onLoadMore();
        }
        // TODO mBusy状态暂时未使用,先注释掉scrollState中的操作,先不要删掉
        switch (scrollState) {
            case OnScrollListener.SCROLL_STATE_IDLE:
                checkIsScrollToBottom();
                // mBusy = false;
                // if (getAdapter() instanceof HeaderViewListAdapter) {
                // if (((HeaderViewListAdapter) getAdapter()).getWrappedAdapter()
                // instanceof BaseListAdapter) {
                // ((BaseListAdapter) ((HeaderViewListAdapter)
                // getAdapter()).getWrappedAdapter()).setBusyState(mBusy);
                // post(loadDateRunnable);
                // }
                // }
                break;
            case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
                // mBusy = false;
                // if (getAdapter() instanceof HeaderViewListAdapter) {
                // if (((HeaderViewListAdapter) getAdapter()).getWrappedAdapter()
                // instanceof BaseListAdapter) {
                // ((BaseListAdapter) ((HeaderViewListAdapter)
                // getAdapter()).getWrappedAdapter()).setBusyState(mBusy);
                // }
                // }
                break;
            case OnScrollListener.SCROLL_STATE_FLING:
                // mBusy = true;
                // if (getAdapter() instanceof HeaderViewListAdapter) {
                // if (((HeaderViewListAdapter) getAdapter()).getWrappedAdapter()
                // instanceof BaseListAdapter) {
                // ((BaseListAdapter) ((HeaderViewListAdapter)
                // getAdapter()).getWrappedAdapter()).setBusyState(mBusy);
                // }
                // }
                break;
            default:
                break;
        }
    }

    public void setLastPage() {
        isLastPage = true;
        removeFooterView(mFooterRelative);
    }

    public void cancelLastPage() {
        isLastPage = false;
        if (getFooterViewsCount() == 0)
            addFooterView(mFooterRelative);
    }

    @SuppressWarnings("unused")
    private Runnable loadDateRunnable = new Runnable() {
        public void run() {
            loadData();
        }
    };

    private void loadData() {
        ((BaseAdapter) ((HeaderViewListAdapter) getAdapter()).getWrappedAdapter()).notifyDataSetChanged();
    }

    // 检测触底用到的变量
    private int getLastVisiblePosition = 0, lastVisiblePositionY = 0;

    /**
     * 检测触底,但如有更多数据,setLastPage之前,会继续加载更多
     */
    private void checkIsScrollToBottom() {
        if (getLastVisiblePosition() == (getCount() - 1)) {
            View itemview = (View) getChildAt(getChildCount() - 1);
            int[] location = new int[2];
            itemview.getLocationOnScreen(location);// 获取在整个屏幕内的绝对坐标
            int y = location[1];
            if (getLastVisiblePosition() != getLastVisiblePosition && lastVisiblePositionY != y) {// 第一次拖至底部
                getLastVisiblePosition = getLastVisiblePosition();
                lastVisiblePositionY = y;
                return;
            } else if (getLastVisiblePosition() == getLastVisiblePosition && lastVisiblePositionY == y) {
                // 第二次拖至底部
                if (isBottomTip) {
                    Toast.makeText(mContext, bottomTipString, Toast.LENGTH_SHORT).show();
                }
            }
        }
        // 未滚动到底部，第二次拖至底部都初始化
        getLastVisiblePosition = 0;
        lastVisiblePositionY = 0;
    }

    public String getCurrentDateTime() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日  HH:mm");
        String date = format.format(new Date());
        return date;
    }

    /**
     * 设置加载更多的footer样式
     *
     * @param footerTipResId    加载更多提示语
     * @param isShowProgressBar 是否显示圆形进度条
     * @param isShowTip         是否显示提示语
     */
    public void setFooterStyle(int footerTipResId, boolean isShowProgressBar, boolean isShowTip) {
        if (isShowProgressBar) {
            mFooterProgressBar.setVisibility(View.VISIBLE);
        } else {
            mFooterProgressBar.setVisibility(View.GONE);
        }
        if (isShowTip) {
            mFooterTextView.setText(footerTipResId);
            mFooterTextView.setVisibility(View.VISIBLE);
        } else {
            mFooterTextView.setVisibility(View.GONE);
        }
    }

    /**
     * 设置列表加载完毕是否提示,以及提示语
     *
     * @param isbottomtip 是否提示
     * @param tip         提示语String
     */
    public void setBottomTip(boolean isbottomtip, String tip) {
        isBottomTip = isbottomtip;
        bottomTipString = tip;
    }

    private static class UIHandler extends Handler {

        private WeakReference<SuperListView> mThis;

        public UIHandler(SuperListView _this) {
            mThis = new WeakReference<SuperListView>(_this);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            if (null == mThis || null == mThis.get()) {
                return;
            }

            switch (msg.what) {
                case TIMEOUT_REFRESH:
                    if (!mThis.get().isRefreshSuccess) {// 下拉刷新等待数据超时
                        mThis.get().onRefreshComplete();
                        // Toast.makeText(mContext, R.string.network_error,
                        // Toast.LENGTH_SHORT).show();
                    }
                    break;
                case TIMEOUT_LOADMORE:
                    if (!mThis.get().isLoadmoreSuccess) {// 载入更多等待数据超时
                        mThis.get().onLoadMoreComplete();
                        // Toast.makeText(mContext, R.string.network_error,
                        // Toast.LENGTH_SHORT).show();
                    }
                    break;
            }
        }
    }
}
